<?php
ob_start();
/*
	控件每次向此文件POST数据
	逻辑：
		1.更新数据库进度
		2.将文件块数据保存到服务器中。
	更新记录：
		2014-04-09 增加文件块验证功能。
		2017-07-11 
			简化文件块逻辑，
			取消进度更新操作
*/
require '../../vendor/autoload.php';
use utils\PathTool;
use utils\CryptoTool;
use model\FileInf;
use biz\up6_biz_event;
use biz\WebSafe;
use utils\HttpHeader;
use utils\ConfigReader;
use biz\PathBuilder;
use utils\FileTool;
use store\StorageType;
use store\MinioTool;

$head = new HttpHeader();

$uid         = $head->param("uid");
$fid         = $head->param("id");
$pid         = $head->param("pid");
$pidRoot     = $head->param("pidRoot");
$md5         = $head->param("md5");
$lenSvr      = $head->param("lenSvr");
$lenLoc      = $head->param("lenLoc");
$blockOffset = $head->param("blockOffset");
$blockSize   = $head->param("blockSize");
$blockIndex  = $head->param("blockIndex");          //当前块索引，基于1
$blockCount  = $head->param("blockCount");          //块总数
$blockMd5    = $head->param("blockMd5");
$complete    = strcmp("true",$head->param("complete"))==0;
$fastdfs_id  = $head->param("fastdfs_id");
$minio_id    = $head->param("minio_id");
$pathSvr     = $_POST["pathSvr"];
$pathRel     = $_POST["pathRel"];
$pathSvr     = PathTool::urldecode_path($pathSvr);
$pathRel     = PathTool::urldecode_path($pathRel);
$pathLoc     = $_FILES['file']['name'];
$token       = $head->param("token");
$pathTmp     = $_FILES['file']['tmp_name'];         //

//相关参数不能为空
if (   (strlen($lenLoc)>0) 
	&& (strlen($uid)>0) 
	&& (strlen($fid)>0) 
    && (strlen($blockOffset)>0) 
	&& !empty($pathSvr))
{
	$verify = false;
	$msg = "";
	$md5Svr = "";
	$stm = FileTool::readAll($pathTmp);
	$blockSizeSvr = filesize($pathTmp);

	$fileSvr = new FileInf();
	$fileSvr->id = $fid;
	$fileSvr->pid = $pid;
	$fileSvr->pidRoot = $pidRoot;
	$fileSvr->fastdfs_id = $fastdfs_id;
	$fileSvr->minio_id = $minio_id;
	$fileSvr->lenSvr = $lenSvr;
	$fileSvr->lenLoc = $lenLoc;
	$fileSvr->pathLoc = $pathLoc;
	$fileSvr->pathSvr = $pathSvr;
	$fileSvr->pathRel = $pathRel;
	$fileSvr->blockIndex = intval($blockIndex);
	$fileSvr->blockOffset = intval($blockOffset);
	$fileSvr->blockCount = intval($blockCount);
	$fileSvr->blockSize = intval($blockSize);	
	$fileSvr->nameLoc = PathTool::getName($fileSvr->pathLoc);
	$fileSvr->nameSvr = $fileSvr->nameLoc;
	$fileSvr->encrypt = ConfigReader::storageEncrypt();//加密存储
	
	//传输加密
	if(ConfigReader::postEncrypt())
	{
	    $ct = new CryptoTool();
	    $pathSvr = $ct->decrypt($pathSvr);
	    if(!$fileSvr->encrypt) $stm = $ct->decodeData($stm,intval($blockSize));
	    //$blockSizeSvr = strlen($stm);
	    //计算解密后的块MD5
	    if( !empty($blockMd5)) $md5Svr = md5($stm);
	}
	else if(!empty($blockMd5)){
	    $md5Svr = md5_file($pathTmp);
	}
	
	//token验证
	$ws = new WebSafe();
	$ret = $ws->validToken($token,$fileSvr,"block");
	//验证失败
	$verify = $ret;
	if(!$verify) exit("token error loc:$token");

	//验证大小
	if($verify) $verify = intval($blockSize) == $blockSizeSvr;
	if( !$verify ) 
	{
	    $msg = "block size error sizeSvr:" . $blockSizeSvr . " sizeLoc:" . $blockSize;
	    exit($msg);
	}
	
	if( $verify && !empty($blockMd5) )
	{
		$verify = $md5Svr == $blockMd5;
		if(!$verify) exit("block md5 error");
	}
	
	if( $verify )
	{
	    $pb = new PathBuilder();
	    $pathSvr = $pb->relToAbs($pathSvr);
	    $fileSvr->pathSvr = $pathSvr;
	    
		//保存文件块数据
		$fw = ConfigReader::blockWriter();
		$needGenId = !empty($pid);
		if($needGenId) $needGenId = 1 == $fileSvr->blockIndex;
		if($needGenId && $fw->storage == StorageType::FastDFS) $needGenId = empty($fastdfs_id);
		if($needGenId && $fw->storage == StorageType::Minio) $needGenId = empty($minio_id);
		if($needGenId)
		{
		    $newid = $fw->make($fileSvr);
		    if($fw->storage == StorageType::IO && empty($newid))
		    {
		        exit("io create error");
		        return;
		    }
		    else if($fw->storage == StorageType::FastDFS)
		    {
		        $fileSvr->fastdfs_id = $newid;
		        if(empty($newid))
		        {
		            exit("FastDFS upload pasrt error");
		            return;
		        }
		    }
		    else if($fw->storage == StorageType::Minio)
		    {
		        $fileSvr->minio_id = $newid;
		        if(empty($newid))
		        {
		            exit("Minio CreateMultipartUpload error");
		            return;
		        }
		    }
		}
		$fileSvr->saveScheme();//保存到层级信息文件
		
		//保存文件块数据
		if( $fw->storage == StorageType::FastDFS) $pathSvr = $fastdfs_id;
		if( $fw->storage == StorageType::Minio) $pathSvr = $minio_id;
		//写入块数据
		$fileSvr->etag = $fw->write($fileSvr, $stm);
		
		if($fw->storage == StorageType::IO && empty($fileSvr->etag))
		{
		    exit("write io block data error");
		    return;
		}
		else if($fw->storage == StorageType::Minio && empty($fileSvr->etag))
		{
		    exit("write minio block data error");
		    return;
		}
		
		//minio->合并块
		if($fw->storage == StorageType::Minio)
		{
		    $fileSvr->saveEtags();
		    if($complete)
		    {
		        if(!MinioTool::completeMultipartUpload($fileSvr))
		        {
		            exit("complete minio upload error");
		            return;
		        }
		    }
		}
		
		up6_biz_event::file_post_block($fid, $blockIndex);		
		
		$obj = array('msg'=>'ok', 
		    'md5'=>$md5Svr, 
		    'offset'=>$blockOffset,
		    array('fields'=>array('fastdfs_id'=>$fastdfs_id,"minio_id"=>$fileSvr->minio_id))		    
		);
		$msg = json_encode($obj);
	}
	echo $msg;
}
else
{
	echo "param is null";
	echo "uid:$uid<br/>";
	echo "fid:$fid<br/>";
	echo "md5:$md5<br/>";
	echo "lenSvr:$lenSvr<br/>";
	echo "lenLoc:$lenLoc<br/>";
	echo "f_pos:$blockOffset<br/>";
	echo "complete:$complete<br/>";
	echo "pathSvr:$pathSvr<br/>";
}
header('Content-Length: ' . ob_get_length());
?>